package cn.lili.modules.goods.serviceimpl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.ResultUtil;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.constant.CommonConstant;
import cn.lili.modules.goods.entity.dos.StoreGoodsLabel;
import cn.lili.modules.goods.entity.dto.StoreGoodsLabelDTO;
import cn.lili.modules.goods.entity.vos.StoreGoodsLabelVO;
import cn.lili.modules.goods.mapper.StoreGoodsLabelMapper;
import cn.lili.modules.goods.service.StoreGoodsLabelService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.transaction.annotation.ShardingTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 店铺商品分类业务层实现
 *
 * @author Bulbasaur
 * @since 2020-03-07 16:18:56
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class StoreGoodsLabelServiceImpl extends ServiceImpl<StoreGoodsLabelMapper, StoreGoodsLabel> implements StoreGoodsLabelService {

    /**
     * 缓存
     */
    private final Cache cache;




    @Override
    public List<StoreGoodsLabelVO> mine() {
        AuthUser currentUser = UserContext.getCurrentUser();
        List<StoreGoodsLabel> list = list(currentUser.getExtendId());
        List<StoreGoodsLabelVO> storeGoodsLabelVOList = new ArrayList<>();

        //循环列表判断是否为顶级，如果为顶级获取下级数据
        list.stream()
                .filter(storeGoodsLabel -> storeGoodsLabel.getLevel() == 0)
                .forEach(storeGoodsLabel -> {
                    StoreGoodsLabelVO storeGoodsLabelVO = new StoreGoodsLabelVO(storeGoodsLabel.getId(),
                            storeGoodsLabel.getLabelName(), storeGoodsLabel.getLevel(), storeGoodsLabel.getSortOrder(), storeGoodsLabel.getPicture());
                    List<StoreGoodsLabelVO> storeGoodsLabelVOChildList = new ArrayList<>();
                    list.stream()
                            .filter(label -> label.getParentId() != null && label.getParentId().equals(storeGoodsLabel.getId()))
                            .forEach(storeGoodsLabelChild -> storeGoodsLabelVOChildList.add(new StoreGoodsLabelVO(storeGoodsLabelChild.getId(), storeGoodsLabelChild.getLabelName(),
                                    storeGoodsLabelChild.getLevel(), storeGoodsLabelChild.getSortOrder(), storeGoodsLabelChild.getPicture())));
                    storeGoodsLabelVO.setChildren(storeGoodsLabelVOChildList);
                    storeGoodsLabelVOList.add(storeGoodsLabelVO);
                });

        //调整店铺分类排序
        storeGoodsLabelVOList.sort(Comparator.comparing(StoreGoodsLabelVO::getSortOrder));
        return storeGoodsLabelVOList;
    }

    @Override
    public List<StoreGoodsLabelVO> listByStoreId(String storeId) {

        //从缓存中获取店铺分类
        if (cache.hasKey(CachePrefix.STORE_CATEGORY.getPrefix() + storeId)) {
            return (List<StoreGoodsLabelVO>) cache.get(CachePrefix.STORE_CATEGORY.getPrefix() + storeId);
        }

        List<StoreGoodsLabel> list = list(storeId);
        List<StoreGoodsLabelVO> storeGoodsLabelVOList = new ArrayList<>();

        //循环列表判断是否为顶级，如果为顶级获取下级数据
        list.stream()
                .filter(storeGoodsLabel -> storeGoodsLabel.getLevel() == 0)
                .forEach(storeGoodsLabel -> {
                    StoreGoodsLabelVO storeGoodsLabelVO = new StoreGoodsLabelVO(storeGoodsLabel.getId(),
                            storeGoodsLabel.getLabelName(), storeGoodsLabel.getLevel(), storeGoodsLabel.getSortOrder());
                    List<StoreGoodsLabelVO> storeGoodsLabelVOChildList = new ArrayList<>();
                    list.stream()
                            .filter(label -> label.getParentId() != null && label.getParentId().equals(storeGoodsLabel.getId()))
                            .forEach(storeGoodsLabelChild -> storeGoodsLabelVOChildList.add(new StoreGoodsLabelVO(storeGoodsLabelChild.getId(), storeGoodsLabelChild.getLabelName(), storeGoodsLabelChild.getLevel(), storeGoodsLabelChild.getSortOrder())));
                    storeGoodsLabelVO.setChildren(storeGoodsLabelVOChildList);
                    storeGoodsLabelVOList.add(storeGoodsLabelVO);
                });

        //调整店铺分类排序
        storeGoodsLabelVOList.sort(Comparator.comparing(StoreGoodsLabelVO::getSortOrder));

        if (!storeGoodsLabelVOList.isEmpty()) {
            cache.put(CachePrefix.CATEGORY.getPrefix() + storeId, storeGoodsLabelVOList);
        }
        return storeGoodsLabelVOList;
    }

    /**
     * 根据分类id集合获取所有店铺分类根据层级排序
     *
     * @param ids 商家ID
     * @return 店铺分类列表
     */
    @Override
    public List<StoreGoodsLabel> listByStoreIds(List<String> ids) {
        return this.list(new LambdaQueryWrapper<StoreGoodsLabel>().in(StoreGoodsLabel::getId, ids).orderByAsc(StoreGoodsLabel::getLevel));
    }

    @Override
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public StoreGoodsLabel addStoreGoodsLabel(StoreGoodsLabel storeGoodsLabel) {
        //获取当前登录商家账号
        AuthUser tokenUser = UserContext.getCurrentUser();
        if (tokenUser == null || CharSequenceUtil.isEmpty(storeGoodsLabel.getStoreId())) {
            throw new ServiceException(ResultCode.USER_NOT_LOGIN);
        }
        //保存店铺分类
        this.save(storeGoodsLabel);
        //清除缓存
        removeCache(storeGoodsLabel.getStoreId());
        return storeGoodsLabel;
    }

    @Override
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public StoreGoodsLabel editStoreGoodsLabel(StoreGoodsLabel storeGoodsLabel) {
        //修改当前店铺的商品分类
        AuthUser tokenUser = UserContext.getCurrentUser();
        if (tokenUser == null || CharSequenceUtil.isEmpty(storeGoodsLabel.getStoreId())) {
            throw new ServiceException(ResultCode.USER_NOT_LOGIN);
        }
        LambdaUpdateWrapper<StoreGoodsLabel> lambdaUpdateWrapper = Wrappers.lambdaUpdate();
        lambdaUpdateWrapper.eq(StoreGoodsLabel::getStoreId, storeGoodsLabel.getStoreId());
        lambdaUpdateWrapper.eq(StoreGoodsLabel::getId, storeGoodsLabel.getId());
        //修改店铺分类
        this.update(storeGoodsLabel, lambdaUpdateWrapper);
        //清除缓存
        removeCache(storeGoodsLabel.getStoreId());
        return storeGoodsLabel;
    }

    @Override
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public void removeStoreGoodsLabel(String storeLabelId) {

        AuthUser tokenUser = UserContext.getCurrentUser();
        if (tokenUser == null || CharSequenceUtil.isEmpty(tokenUser.getExtendId())) {
            throw new ServiceException(ResultCode.USER_NOT_LOGIN);
        }
        //删除店铺分类
        this.removeById(storeLabelId);

        //清除缓存
        removeCache(tokenUser.getExtendId());
    }

    @Override
    public List<Map<String, Object>> listMapsByStoreIds(List<String> ids, String columns) {
        QueryWrapper<StoreGoodsLabel> queryWrapper = new QueryWrapper<StoreGoodsLabel>().in("id", ids).orderByAsc("level");
        queryWrapper.select(columns);
        return this.listMaps(queryWrapper);
    }

    /**
     * 获取店铺商品分类列表
     *
     * @param storeId 店铺ID
     * @return 店铺商品分类列表
     */
    private List<StoreGoodsLabel> list(String storeId) {
        LambdaQueryWrapper<StoreGoodsLabel> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(StoreGoodsLabel::getStoreId, storeId);
        queryWrapper.orderByDesc(StoreGoodsLabel::getSortOrder);
        return this.baseMapper.selectList(queryWrapper);
    }

    /**
     * 清除缓存
     */
    private void removeCache(String storeId) {
        cache.remove(CachePrefix.STORE_CATEGORY.getPrefix() + storeId);
    }


    /**
     * 根据店铺id获取分类集合
     * @param dto
     * @return
     */
    private Page<StoreGoodsLabel> selectGoodsLabellistByStoreId(StoreGoodsLabelDTO dto) {
        LambdaQueryWrapper<StoreGoodsLabel> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(true,StoreGoodsLabel::getStoreId, dto.getStoreId());
        queryWrapper.eq(StrUtil.isNotEmpty(dto.getParentId()), StoreGoodsLabel::getParentId, dto.getParentId());
        queryWrapper.orderByDesc(StoreGoodsLabel::getSortOrder);
        return this.baseMapper.selectPage(new Page<>(dto.getPageNumber(), dto.getPageSize(),false), queryWrapper);
    }

    private Page<StoreGoodsLabel> selectFreeTaxGoodsLabellist(StoreGoodsLabelDTO dto) {
        return baseMapper.selectFreeTaxGoodsLabellist(new Page<>(dto.getPageNumber(), dto.getPageSize()), dto);
    }


    /**
     * 获取免税商品的分类
     * @param dto
     * @return
     */
    @Override
    public List<StoreGoodsLabelVO> getFreeTaxGoodsLabelList(StoreGoodsLabelDTO dto) {
        List<StoreGoodsLabelVO> vos = new ArrayList<>();
        String redisKey = CachePrefix.STORE_CATEGORY.getPrefix() + "freeTax";
        //从缓存中获取店铺分类
        if (cache.hasKey(redisKey)) {
            List<StoreGoodsLabelVO> voList = (List<StoreGoodsLabelVO>) cache.get(redisKey);
            for (int i = 0; i < voList.size() - 1; i++) {
                Object obj = cache.get(CommonConstant.STORE_CATEGORY_NUM + voList.get(i).getId());
                if (obj == null || Double.valueOf(obj.toString()) <= 0) {
                    voList.remove(i);
                }
            }
            if (CollUtil.isNotEmpty(voList)) {
                return voList;
            }
        }
        StoreGoodsLabel goodsLabel = new StoreGoodsLabel();
        goodsLabel.setParentId("0");
        goodsLabel.setStoreId(dto.getStoreId());
        //Page<StoreGoodsLabel> page = this.selectGoodsLabellistByStoreId(dto);
        Page<StoreGoodsLabel> page = this.selectFreeTaxGoodsLabellist(dto);
        if (CollUtil.isNotEmpty(page.getRecords())) {
            log.info("#getFreeTaxGoodsLabelList# 查找免税店铺分类,page.getRecords():{}", JSONObject.toJSONString(page.getRecords()));
            page.getRecords().stream().forEach(e -> {
                Object obj = cache.get(CommonConstant.STORE_CATEGORY_NUM + e.getId());
                
                if (obj == null || Double.valueOf(obj.toString()) <= 0) {
                    //跳过此次操作
                    return;
                }
                StoreGoodsLabelVO vo = new StoreGoodsLabelVO();
                vo.setId(e.getId());
                vo.setLabelName(e.getLabelName());
                vo.setLevel(e.getLevel());
                vo.setPicture(StrUtil.isNotBlank(e.getPicture()) ? e.getPicture() : "");
                vos.add(vo);
            });
            cache.put(redisKey, vos, 30L, TimeUnit.SECONDS);
        }
        return vos;
    }

    @Override
    public ResultMessage<Object> getRedisCacheGoodLabel(Integer type, String categoryId) {
        String redisKey = CachePrefix.STORE_CATEGORY.getPrefix() + "freeTax";
        if (type == 0) {
            Object obj = null;
            if (StrUtil.isNotEmpty(categoryId)) {
                obj = cache.get(CommonConstant.STORE_CATEGORY_NUM + categoryId);
            } else {
                obj = cache.keys(CommonConstant.STORE_CATEGORY_NUM );
            }
            return ResultUtil.data(obj);
        } else {
            cache.remove(redisKey);
            return ResultUtil.success();
        }
    }
}
